package edu.simplemqom.client;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import edu.simplemqom.client.Queue.Acces;
import edu.simplemqom.objects.SMQOMQueueRights;
import edu.simplemqom.protocol.SMQOMCommandId;
import edu.simplemqom.protocol.SMQOMPackage;
import edu.simplemqom.protocol.SMQOMProtocol;

public class Channel {
	
	private Connection connection;
	
	protected Channel(Connection conn) {
		this.connection = conn;
	}
	
	public Queue getQueue(String name, Queue.Acces rights) throws SMQOMException {
		if (name == null) {
			return null;
		}
		
		InputStream input;
		OutputStream output;
		try {
			input = connection.getInputStream();
			output = connection.getOutputStream();
		} catch (IOException e1) {
			throw new SMQOMException(e1);
		}
		
		int type;
		byte brokerRights;
		if (rights == Acces.CONSUMER) {
			type = Queue.Type.IN;
			brokerRights = SMQOMQueueRights.CONSUMER;
		} else if (rights == Acces.PRODUCER) {
			type = Queue.Type.OUT;
			brokerRights = SMQOMQueueRights.PRODUCER;
		} else if (rights == Acces.ADMIN) {
			type = Queue.Type.IN_OUT;
			brokerRights = SMQOMQueueRights.ADMIN;
		} else {
			throw new SMQOMException("Bad rights requested");
		}
		
		byte[] qName = name.getBytes();
		byte[] body2 = new byte[qName.length+1];
		body2[0] = brokerRights;

		System.arraycopy(qName, 0, body2, 1, qName.length);
		
		try {
			output.write(new SMQOMPackage(SMQOMCommandId.REQ_QUEUE, connection.getSessionId(), body2).getBytes());
			output.flush();
		} catch (IOException e) {
			throw new SMQOMException("IOException when opening queue: " + e.getMessage());
		}
		
		try {
			SMQOMPackage pack = SMQOMProtocol.readPackageFromStream(input);
			
			if (pack.getCommandId() == SMQOMCommandId.SND_QUEUE_ACK) {
				
				Queue queue = new Queue(name, type, this);
				
				output.write(new SMQOMPackage(SMQOMCommandId.ACK, pack.getSessionId(), null).getBytes());
				output.flush();
				
				return queue;
			} else if(pack.getCommandId() == SMQOMCommandId.SND_REQ_DENY) {
				output.write(new SMQOMPackage(SMQOMCommandId.ACK, pack.getSessionId(), null).getBytes());
				output.flush();
				throw new SMQOMException("Broker denied access to queue. Bad queue name or requested rights.");
			} else {
				throw new SMQOMException("Received unknown answet from broker. Command Id: " + pack.getCommandId() + "; Data length: " + pack.getDataSize());
			}
		} catch (IOException e) {
			throw new SMQOMException("IOException when opening queue: " + e.getMessage(), e);
		}
	}
	
	public boolean queueExists(String name) throws SMQOMException {
		if (name == null) {
			return false;
		}
		
		InputStream input;
		OutputStream output;
		try {
			input = connection.getInputStream();
			output = connection.getOutputStream();
		} catch (IOException e1) {
			throw new SMQOMException(e1);
		}
		
		byte[] qName = name.getBytes();
	
		try {
			output.write(new SMQOMPackage(SMQOMCommandId.REQ_QUEUE_EXISTS, connection.getSessionId(), qName).getBytes());
			output.flush();
			
			SMQOMPackage pack = SMQOMProtocol.readPackageFromStream(input);
			if (pack.getCommandId() == SMQOMCommandId.SND_QUEUE_EXISTS_ACK) {
				return true;
			} else if (pack.getCommandId() == SMQOMCommandId.SND_REQ_DENY) {
				return false;
			} else if (pack.getCommandId() == SMQOMCommandId.UNKNOWN_PACKAGE) {
				throw new SMQOMException("Broker sent UNKNOWN_PACKAGE in response");
			} else {
				throw new SMQOMException("Reeived unexpected package from broker");
			}
		} catch (IOException e) {
			throw new SMQOMException("IOExceptionn on Queue existence checking.", e);
		}
	}
	
	protected OutputStream getOutputStream() throws IOException {
		return connection.getOutputStream();
	}
	
	protected InputStream getInputStream() throws IOException {
		return connection.getInputStream();
	}
	
	protected int getSessionId() {
		return connection.getSessionId();
	}
}
